﻿
Imports System.Runtime.CompilerServices
Imports System.IO
Imports osi.root.constants
Imports osi.root.connector
Imports osi.root.utils
Imports osi.root.formation

Public Module _stream
    <Extension()> Public Function write(ByVal s As Stream,
                                        ByVal buff() As Byte,
                                        ByVal offset As Int32,
                                        ByVal count As Int32) As event_comb
        Return create(Function() As Boolean
                          Return Not s Is Nothing AndAlso
                                 s.CanWrite() AndAlso
                                 offset >= 0 AndAlso
                                 count >= 0 AndAlso
                                 array_size(buff) >= offset + count
                      End Function,
                      Function() As event_comb
                          Return New event_comb_async_operation(
                                            Function(a As AsyncCallback) As IAsyncResult
                                                Return s.BeginWrite(buff,
                                                                    offset,
                                                                    count,
                                                                    a,
                                                                    Nothing)
                                            End Function,
                                            Sub(ar As IAsyncResult)
                                                s.EndWrite(ar)
                                            End Sub)
                      End Function)
    End Function

    <Extension()> Public Function write(ByVal s As Stream, ByVal buff() As Byte, ByVal count As Int32) As event_comb
        Return write(s, buff, 0, count)
    End Function

    <Extension()> Public Function write(ByVal s As Stream, ByVal buff() As Byte) As event_comb
        Return write(s, buff, array_size(buff))
    End Function

    <Extension()> Public Function read(ByVal s As Stream,
                                       ByVal b() As Byte,
                                       ByVal offset As Int32,
                                       ByVal count As Int32,
                                       Optional ByVal r As pointer(Of Int32) = Nothing) As event_comb
        Return create(Function() As Boolean
                          Return Not s Is Nothing AndAlso
                                 s.CanRead() AndAlso
                                 offset >= 0 AndAlso
                                 count >= 0 AndAlso
                                 array_size(b) >= offset + count
                      End Function,
                      Function() As event_comb
                          Return event_comb_async_operation.ctor(
                                      Function(ac As AsyncCallback) As IAsyncResult
                                          Return s.BeginRead(b,
                                                             offset,
                                                             count,
                                                             ac,
                                                             Nothing)
                                      End Function,
                                      Function(ar As IAsyncResult) As Int32
                                          Return s.EndRead(ar)
                                      End Function,
                                      r)
                      End Function)
    End Function

    <Extension()> Public Function read(ByVal s As Stream,
                                       ByVal b() As Byte,
                                       ByVal count As Int32,
                                       Optional ByVal r As pointer(Of Int32) = Nothing) As event_comb
        Return read(s, b, 0, count, r)
    End Function

    <Extension()> Public Function read(ByVal s As Stream,
                                       ByVal b() As Byte,
                                       Optional ByVal r As pointer(Of Int32) = Nothing) As event_comb
        Return read(s, b, array_size(b), r)
    End Function

    Private Function copy_to_single(ByVal i As Stream,
                                    ByVal o As Stream,
                                    ByVal count As Int32,
                                    Optional ByVal result As pointer(Of Int32) = Nothing) As event_comb
        Dim rec As event_comb = Nothing
        Dim wec As event_comb = Nothing
        Dim b() As Byte = Nothing
        Dim r As pointer(Of Int32) = Nothing
        Return New event_comb(Function() As Boolean
                                  If count < 0 Then
                                      Return False
                                  ElseIf count = 0 Then
                                      Return goto_end()
                                  Else
                                      If array_size(b) <> count Then
                                          ReDim b(count - 1)
                                      End If
                                      r = New pointer(Of Int32)()
                                      rec = read(i, b, r)
                                      Return waitfor(rec) AndAlso
                                             goto_next()
                                  End If
                              End Function,
                              Function() As Boolean
                                  If rec.end_result() Then
                                      If +r = 0 Then
                                          Return eva(result, 0) AndAlso goto_end()
                                      Else
                                          wec = write(o, b, +r)
                                          Return waitfor(wec) AndAlso
                                                 goto_next()
                                      End If
                                  Else
                                      Return False
                                  End If
                              End Function,
                              Function() As Boolean
                                  Return wec.end_result() AndAlso
                                         eva(result, +r) AndAlso
                                         goto_end()
                              End Function)
    End Function

    <Extension()> Public Function copy_to(ByVal i As Stream,
                                          ByVal o As Stream,
                                          ByVal count As Int64,
                                          ByVal buff_size As Int32,
                                          ByVal single_copy_timeout_ms As Int64,
                                          Optional ByVal result As pointer(Of Int64) = Nothing) As event_comb
        Dim r As pointer(Of Int32) = Nothing
        Dim ec As event_comb = Nothing
        r = New pointer(Of Int32)()
        Dim oc As Int64 = 0
        oc = count
        Return event_comb.repeat(Function(x As Int32) As Boolean
                                     If count > 0 AndAlso (+r) > 0 Then
                                         Return True
                                     Else
                                         eva(result, oc - count)
                                         Return False
                                     End If
                                 End Function,
                                 Function() As event_comb
                                     Return New event_comb(Function() As Boolean
                                                               ec = copy_to_single(i, o, min(buff_size, count), r)
                                                               Return waitfor(ec, single_copy_timeout_ms) AndAlso
                                                                      goto_next()
                                                           End Function,
                                                           Function() As Boolean
                                                               If ec.end_result() Then
                                                                   count -= (+r)
                                                                   Return goto_end()
                                                               Else
                                                                   Return False
                                                               End If
                                                           End Function)
                                 End Function)
    End Function

    <Extension()> Public Function copy_to(ByVal i As Stream,
                                          ByVal o As Stream,
                                          ByVal count As Int64,
                                          ByVal single_copy_timeout_ms As Int64,
                                          Optional ByVal result As pointer(Of Int64) = Nothing) As event_comb
        Return copy_to(i, o, count, 4096, single_copy_timeout_ms, result)
    End Function

    <Extension()> Public Function copy_to(ByVal i As Stream,
                                          ByVal o As Stream,
                                          ByVal single_copy_timeout_ms As Int64,
                                          Optional ByVal result As pointer(Of Int64) = Nothing) As event_comb
        Return copy_to(i, o, maxInt64, single_copy_timeout_ms, result)
    End Function

    <Extension()> Public Function copy_to(ByVal i As Stream,
                                          ByVal o As Stream,
                                          Optional ByVal result As pointer(Of Int64) = Nothing) As event_comb
        Return copy_to(i, o, maxInt64, result)
    End Function
End Module
